package com.caocaog.market.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.caocaog.market.entity.ShopPrinter;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.HttpClientUtil;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.Map;

/**
 * 易联云打印机工具类
 *
 * @author chechen
 * @date 2021-12-17
 * @see <a href="http://doc2.10ss.net/331992">易联云云打印开发文档</a>
 */
public class YlyPrinterUtil {

    private YlyPrinterUtil(){}

    /** 应用ID */
    private static final String CLIENT_ID = "1075201596";
    /** 应用密钥 */
    private static final String CLIENT_SECRET = "be1a74da3fee1e259f6c3ec8a158a21f";
    private static final String GRANT_TYPE = "client_credentials";
    private static final String SCOPE = "all";
    private static final String ACCESS_TOKEN = "4476b81c7f6e4fc284f991ebc4365e61";
    private static final Map<String, String> PRINTER_STATUS_MAP = new HashMap<>();
    static {
        PRINTER_STATUS_MAP.put("0", "离线");
        PRINTER_STATUS_MAP.put("1", "在线");
        PRINTER_STATUS_MAP.put("2", "缺纸");
    }
    private static final String ERROR_MESSAGE = "易联云开放平台 api 无返回结果";

    /** 易联云自有应用服务模式获取Access Token的地址 */
    private static final String GET_ACCESS_TOKEN_URL = "https://open-api.10ss.net/oauth/oauth";
    /** 终端授权 */
    private static final String TERMINAL_AUTHORIZATION_URL = "https://open-api.10ss.net/printer/addprinter";
    /** 删除终端 */
    private static final String DELETE_TERMINAL_URL = "https://open-api.10ss.net/printer/deleteprinter";
    /** 终端状态 */
    private static final String PRINTER_STATUS_URL = "https://open-api.10ss.net/printer/getprintstatus";
    /** 文本打印 */
    private static final String TEXT_PRINT_URL = "https://open-api.10ss.net/print/index";

    /**
     * 易联云打印信息
     *
     * @param orderInfo   要打印的订单信息
     * @param machineCode 打印机终端号
     * @param cascadeCount 打印次数
     */
    public static String print(String orderInfo, String machineCode, int cascadeCount) {
        Map<String, String> params = getParams(machineCode, IdUtil.randomUUID());
        params.put("content", orderInfo);
        params.put("origin_id", IdUtil.objectId());

        PostMethod post = HttpClientUtil.post(TEXT_PRINT_URL, params,
                new Header("Content-Type", "application/x-www-form-urlencoded"));

        for (int i = 0; i < cascadeCount; i++) {
            unifiedProcessingResult(post);
        }
        return null;
    }

    /**
     * 终端授权 (永久授权)
     *
     * @param shopPrinter 打印机信息
     * @return 是否成功
     */
    public static String addPrinter(ShopPrinter shopPrinter) {
        Map<String, String> params = getParams(shopPrinter.getNumber(), IdUtil.randomUUID());
        params.put("msign", shopPrinter.getPrinterKey());
        params.put("phone", shopPrinter.getSimNumber());
        params.put("print_name", shopPrinter.getName());

        PostMethod post = HttpClientUtil.post(TERMINAL_AUTHORIZATION_URL, params);
        return unifiedProcessingResult(post);
    }

    /**
     * 删除终端授权
     *
     * @param machineCode 易联云打印机终端号
     * @return 是否成功
     */
    public static String deletePrinter(String machineCode) {
        Map<String, String> params = getParams(machineCode, IdUtil.randomUUID());

        PostMethod post = HttpClientUtil.post(DELETE_TERMINAL_URL, params);
        return unifiedProcessingResult(post);
    }

    /**
     * 获取终端状态
     *
     * @param machineCode 易联云打印机终端号
     * @return 终端状态
     */
    public static Result<String> getStatus(String machineCode) {
        Map<String, String> params = getParams(machineCode, IdUtil.randomUUID());

        PostMethod post = HttpClientUtil.post(PRINTER_STATUS_URL, params);
        JSONObject resultJsonObject;
        try {
            resultJsonObject = JSONObject.parseObject(post.getResponseBodyAsString());
            System.out.println(resultJsonObject);
            if ("0".equals(resultJsonObject.getString("error")))
                return Result.OK(PRINTER_STATUS_MAP.get(resultJsonObject.getJSONObject("body").getString("state")));
            return Result.error(null, resultJsonObject.getString("error_description"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Result.OK("未知");
    }

    /**
     * 获取 Access Token
     * 如果 Access Token 失效请手动调用此接口
     *
     * @see <a href="http://doc2.10ss.net/371770">易联云自有应用服务模式开发文档</a>
     */
    public static String getAccessToken() {
        // 获取北京时间（UTC+08:00）秒数
        final String TIMESTAMP = String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));

        Map<String, String> params = new HashMap<String, String>() {{
            put("client_id", CLIENT_ID);
            put("sign", signature(TIMESTAMP));
            put("timestamp", TIMESTAMP);
            put("id", IdUtil.randomUUID());
            put("grant_type", GRANT_TYPE);
            put("scope", SCOPE);
        }};

        PostMethod post = HttpClientUtil.post(GET_ACCESS_TOKEN_URL, params);
        try {
            JSONObject resultJsonObject = JSONObject.parseObject(post.getResponseBodyAsString());
            return resultJsonObject.getJSONObject("body").getString("access_token");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 生成签名字符串
     *
     * @param timestamp 时间戳
     * @return 签名字符串
     */
    private static String signature(String timestamp) {
        return SecureUtil.md5(CLIENT_ID + timestamp + CLIENT_SECRET);
    }

    /**
     * 返回通用的请求参数
     *
     * @param machineCode 终端编号
     * @param id 订单号
     * @return 请求参数
     */
    private static Map<String, String> getParams(String machineCode, String id) {
        // 获取北京时间（UTC+08:00）秒数
        final String TIMESTAMP = String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));

        return new HashMap<String, String>() {{
            put("access_token", ACCESS_TOKEN);
            put("machine_code", machineCode);
            put("client_id", CLIENT_ID);
            put("sign", signature(TIMESTAMP));
            put("timestamp", TIMESTAMP);
            put("id", id);
        }};
    }

    /**
     * 统一处理返回结果
     * 请求成功返回null，请求失败返回错误信息
     *
     * @param post 返回结果
     * @return 错误信息/null
     */
    private static String unifiedProcessingResult(PostMethod post) {
        try {
            String responseBodyAsString = post.getResponseBodyAsString();
            if (StringUtils.isBlank(responseBodyAsString))
                return ERROR_MESSAGE;
            JSONObject resultJsonObject = JSON.parseObject(responseBodyAsString);
            System.out.println(resultJsonObject);
            if ("0".equals(resultJsonObject.getString("error"))) return null;
            return resultJsonObject.getString("error_description");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ERROR_MESSAGE;
    }

}
